package com.service;

import static com.def.GenericDef.EMPTY_CARRIER;
import static com.def.GenericDef.EVT_BOX_CHANGE;
import static com.def.GenericDef.EXIST_CARRIER;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_XPBOXCHG_BOX_SLOT_CHK_FAILED;
import static com.def.GenericDef.E_XPBOXCHG_DIFF_BOX_ADMIN_FLG_WHEN_CHANGE_WO;
import static com.def.GenericDef.E_XPBOXCHG_INVALID_INPUT;
import static com.def.GenericDef.E_XPBOXCHG_INVALID_NEW_BOX_STAT;
import static com.def.GenericDef.E_XPBOXCHG_INVALID_OLD_BOX_STAT;
import static com.def.GenericDef.E_XPBOXCHG_NEW_BOX_ID_NULL;
import static com.def.GenericDef.E_XPBOXCHG_NEW_BOX_REAL_EMPT_CHK_NG;
import static com.def.GenericDef.E_XPBOXCHG_NO_PRD_IN_NEW_BOXG;
import static com.def.GenericDef.E_XPBOXCHG_NO_PRD_IN_OLD_BOXG;
import static com.def.GenericDef.E_XPBOXCHG_OLD_BOX_ID_NULL;
import static com.def.GenericDef.E_XPBOXCHG_OLD_BOX_REAL_EMPT_CHK_NG;
import static com.def.GenericDef.PROC_COMPLETE;
import static com.def.GenericDef.PROC_EMPTY;
import static com.def.GenericDef.PROC_SHIP;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.SHT_WO_ID_MIX;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPBOXCHG;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef._YES;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.icim.service.ICIMBaseService;
import com.model.Ret_box;
import com.model.Ret_prd_info;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.SimpleRtnBeen;
import com.tx.xpboxchg.XpboxchgI;
import com.tx.xpboxchg.XpboxchgIA_N;
import com.tx.xpboxchg.XpboxchgIA_O;
import com.tx.xpboxchg.XpboxchgO;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpboxchgService")
public class XpboxchgService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpboxchgService.class);
	private static String TX_NAME = T_XPBOXCHG;

	private XpboxchgI inTrx;
	private XpboxchgO outTrx;
	private MqOpe mqOpe;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;

	private String gszMsgBuf = "";

	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;

	private Ret_box gOld_box = new Ret_box();
	private Ret_box gNew_box = new Ret_box();
	private List<Ret_prd_info> gOld_prdList = new ArrayList<Ret_prd_info>();
	private List<Ret_prd_info> gNew_prdList = new ArrayList<Ret_prd_info>();

	public String subMainProc(String strInMsg) {
		Session session = retPrdInfoDao.getCrSession();
		long rtnCode = _NORMAL;
		String outMsg = null;

		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		inTrx = new XpboxchgI();
		outTrx = new XpboxchgO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		outTrx.setType_id(TRX_OUT);

		mqOpe = new MqOpe();

		try {
			inTrx = (XpboxchgI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				session.flush();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
		}
		return outMsg;
	}

	/**
	 * Real action type
	 * 
	 * @param actionType
	 * @return
	 */
	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;
		switch (actionType) {
		case 'C': {
			lRc = boxChgFunc();
			if (lRc != _NORMAL) {
				return lRc;
			}
			break;
		}

		default: {
			gszMsgBuf = "Invalide type input: [" + actionType + "]";
			return E_XPBOXCHG_INVALID_INPUT;
		}
		}

		return lRc;
	}

	/**
	 * 检查输入数据
	 * 
	 * @return
	 */
	private SimpleRtnBeen inputChk() {
		if (Util.isSpaceCheck(inTrx.getNew_box_id())) {
			gszMsgBuf = "右侧箱号不能为空![" + inTrx.getNew_box_id() + "]";
			return new SimpleRtnBeen(E_XPBOXCHG_NEW_BOX_ID_NULL, gszMsgBuf);
		}
		if (Util.isSpaceCheck(inTrx.getOld_box_id())) {
			gszMsgBuf = "左侧箱号不能为空![" + inTrx.getOld_box_id() + "]";
			return new SimpleRtnBeen(E_XPBOXCHG_OLD_BOX_ID_NULL, gszMsgBuf);
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * 交换箱
	 * 
	 * @return
	 */
	private long boxChgFunc() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		long lRc = _NORMAL;

		rtnBeen = inputChk();
		if (_NORMAL != lRc) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}
		// 查询并检查原箱
		rtnBeen = chkOldBox();
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}

		// 查询并检查右侧箱
		rtnBeen = chkNewBox();
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}

		lRc = checkPrdQrsProc();
		if(lRc != _NORMAL){
			return lRc;
		}
		
		// 查询并检查原箱prd信息
		rtnBeen = chkOldPrdInfo();
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}

		// 查询并检查右侧箱prd信息
		rtnBeen = chkNewPrdInfo();
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}
		
	


		// 更新Prd信息
		lRc = realChgPrdInfo();
		if (_NORMAL != lRc) {
			return lRc;
		}

		// 配置Box信息
		lRc = configBoxProc();
		if (_NORMAL != lRc) {
			return lRc;
		}
		
		
		return _NORMAL;
	}

	/**
	 * 检查原箱信息
	 * 
	 * @return SimpleRtnBeen{Ret_box}
	 */
	private SimpleRtnBeen chkOldBox() {
		gOld_box = retBoxDao.getWithLock(inTrx.getOld_box_id(),
				LockMode.UPGRADE);
		if (null == gOld_box) {
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND,
					new NotFoundRtnBeen(inTrx.getOld_box_id(), Ret_box.class)
							.toString());
		}

		// Status check
		if (PROC_WAIT.equals(gOld_box.getBox_stat())
				|| PROC_COMPLETE.equals(gOld_box.getBox_stat())
				|| PROC_EMPTY.equals(gOld_box.getBox_stat())) {
			;
		} else if (PROC_SHIP.equals(gOld_box.getBox_stat())
				&& !Util.isSpaceCheck(inTrx.getIn_bank())
				&& inTrx.getIn_bank().equals(_YES)) {
			;
		} else {
			return new SimpleRtnBeen(E_XPBOXCHG_INVALID_OLD_BOX_STAT, "左侧箱号 ["
					+ inTrx.getOld_box_id() + "]状态为 [" + gOld_box.getBox_stat()
					+ "],状态无效!");
		}

		// Check real empt
		if (!PROC_EMPTY.equals(gOld_box.getBox_stat())
				&& EXIST_CARRIER.equals(gOld_box.getReal_emp())) {
			;// 非空BOX
		} else if (PROC_EMPTY.equals(gOld_box.getBox_stat())
				&& EMPTY_CARRIER.equals(gOld_box.getReal_emp())) {
			;// 真空BOX
		} else {
			return new SimpleRtnBeen(E_XPBOXCHG_OLD_BOX_REAL_EMPT_CHK_NG,
					"左侧箱号真空状态检查NG, 箱子状态是[" + gOld_box.getBox_stat()
							+ "], 但真空标记(real_empt)是[" + gOld_box.getReal_emp()
							+ "]!");
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * 检查右侧箱信息
	 * 
	 * @return SimpleRtnBeen{Ret_box}
	 */
	private SimpleRtnBeen chkNewBox() {
		gNew_box = retBoxDao.getWithLock(inTrx.getNew_box_id(),
				LockMode.UPGRADE);
		if (null == gNew_box) {
			return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND,
					new NotFoundRtnBeen(inTrx.getNew_box_id(), Ret_box.class)
							.toString());
		}

		// Status check
		if (PROC_WAIT.equals(gNew_box.getBox_stat())
				|| PROC_COMPLETE.equals(gNew_box.getBox_stat())
				|| PROC_EMPTY.equals(gNew_box.getBox_stat())) {
			;
		} else if (PROC_SHIP.equals(gNew_box.getBox_stat())
				&& !Util.isSpaceCheck(inTrx.getIn_bank())
				&& inTrx.getIn_bank().equals(_YES)) {
			;
		} else {
			return new SimpleRtnBeen(E_XPBOXCHG_INVALID_NEW_BOX_STAT, "右侧箱号["
					+ inTrx.getNew_box_id() + "]状态为 [" + gNew_box.getBox_stat()
					+ "],状态无效!");
		}

		// Check real empt
		if (!PROC_EMPTY.equals(gNew_box.getBox_stat())
				&& EXIST_CARRIER.equals(gNew_box.getReal_emp())) {
			;// 非空BOX
		} else if (PROC_EMPTY.equals(gNew_box.getBox_stat())
				&& EMPTY_CARRIER.equals(gNew_box.getReal_emp())) {
			;// 真空BOX
		} else {
			return new SimpleRtnBeen(E_XPBOXCHG_NEW_BOX_REAL_EMPT_CHK_NG,
					"右侧箱号真空状态检查NG, 箱子状态是[" + gNew_box.getBox_stat()
							+ "], 但真空标记(real_empt)是[" + gNew_box.getReal_emp()
							+ "]!");
		}
		
//		箱子状态为EMPTY，不卡控内部订单
		if (PROC_EMPTY.equals(gNew_box.getBox_stat()) 
				|| PROC_EMPTY.equals(gOld_box.getBox_stat())){
			return new SimpleRtnBeen(_NORMAL);
		}

		// Check wo
		if(!gOld_box.getWo_id_fk().equals(gNew_box.getWo_id_fk())){
			return new SimpleRtnBeen(
					SHT_WO_ID_MIX,
					"两个箱子的内部订单号不同，请确认！" + "左侧箱号["
							+ gOld_box.getBox_id() + "]，内部订单["
							+ gOld_box.getWo_id_fk() + "]，状态["
							+ gOld_box.getBox_stat() + "]" + "右侧箱号["
							+ gNew_box.getBox_id() + "]，内部订单["
							+ gNew_box.getWo_id_fk() + "]，状态["
							+ gNew_box.getBox_stat() + "]");
		}
		
		//Check PRD_ADMIN_FLG
		if(gOld_box.getBnk_flg().equals("2") || gNew_box.getBnk_flg().equals("2")){
			if(null != gOld_box.getPrd_admin_flg() && null != gNew_box.getPrd_admin_flg()){
				if( (!PROC_EMPTY.equals(gNew_box.getBox_stat())) && (!PROC_EMPTY.equals(gOld_box.getBox_stat()))   
						&&	(!gOld_box.getPrd_admin_flg().substring(0,1).equals(gNew_box.getPrd_admin_flg().substring(0,1))) ){
						return new SimpleRtnBeen(
								E_XPBOXCHG_DIFF_BOX_ADMIN_FLG_WHEN_CHANGE_WO,
								"两个箱子的半成品可出货状态不同，请确认！" + "左侧箱号["
										+ gOld_box.getBox_id() + "]，半成品可出货状态["
										+ gOld_box.getPrd_admin_flg().substring(0,1) + "]，右侧箱号["
										+ gNew_box.getBox_id() + "]，半成品可出货状态["
										+ gNew_box.getPrd_admin_flg().substring(0,1) + "]");
					}
				
			}			
		}
		

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * 检查原箱中prd信息
	 * 
	 * @param box_id
	 * @return
	 */
	private SimpleRtnBeen chkOldPrdInfo() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);

		gOld_prdList = retPrdInfoDao.getShtListInfoWithLock(inTrx.getOld_box_id());
		if (null == gOld_prdList) {
			if (!PROC_EMPTY.equals(gOld_box.getBox_stat())) {
				return new SimpleRtnBeen(E_XPBOXCHG_NO_PRD_IN_OLD_BOXG, "左侧箱号["
						+ inTrx.getOld_box_id() + "]状态非空,但箱子中找不到产品ID! ");
			}
		} else {
			rtnBeen = mappingPrdInTrxWithDB(gOld_prdList, gOld_box);
			if (_NORMAL != rtnBeen.getlRc()) {
				return rtnBeen;
			} else {
				gOld_prdList = (List<Ret_prd_info>) rtnBeen.getObj();
			}
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * 检查右侧箱子中prd信息
	 * 
	 * @param box_id
	 * @return
	 */
	private SimpleRtnBeen chkNewPrdInfo() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);

		gNew_prdList = retPrdInfoDao.getShtListInfoWithLock(inTrx
				.getNew_box_id());
		if (null == gNew_prdList) {
			if (!PROC_EMPTY.equals(gNew_box.getBox_stat())) {
				return new SimpleRtnBeen(E_XPBOXCHG_NO_PRD_IN_NEW_BOXG, "右侧箱号["
						+ inTrx.getNew_box_id() + "]状态非空,但箱子中找不到产品ID! ");
			}
		} else {
			rtnBeen = mappingPrdInTrxWithDB(gNew_prdList, gNew_box);
			if (_NORMAL != rtnBeen.getlRc()) {
				return rtnBeen;
			} else {
				gNew_prdList = (List<Ret_prd_info>) rtnBeen.getObj();
			}
		}

		return new SimpleRtnBeen(_NORMAL);
	}

	/**
	 * 检查DB中查询到的Prd在inTrx中是否存在，存在则更新box id和slot no为inTrx中的值，不存在则报错
	 * 
	 * @param prdList
	 * @param box
	 * @return SimpleRtnBeen {List<Ret_prd_info>}
	 */
	private SimpleRtnBeen mappingPrdInTrxWithDB(List<Ret_prd_info> prdList,
			Ret_box box) {
		int iO = 0, iN = 0;
		int iOLen = 0;
		int iNLen = 0;
		if (null != inTrx.getIary_old()) {
			iOLen = inTrx.getIary_old().size();
		}
		if (null != inTrx.getIary_new()) {
			iNLen = inTrx.getIary_new().size();
		}
		for (Ret_prd_info Prd : prdList) {
			for (iO = 0; iO < iOLen; iO++) {
				if (Prd.getPrd_seq_id().equals(inTrx.getIary_old().get(iO).getPrd_seq_id())) {
					Prd.setBox_id_fk(inTrx.getOld_box_id());
					break;
				}
			}
			for (iN = 0; iN < iNLen; iN++) {
				if (Prd.getPrd_seq_id().equals(inTrx.getIary_new().get(iN).getPrd_seq_id())) {
					Prd.setBox_id_fk(inTrx.getNew_box_id());
					// Prd.setSlot_no(inTrx.getIary_new().get(iN).getSlot_no());
					break;
				}
			}
			if ((iO < iOLen) && !(iN < iNLen) || !(iO < iOLen) && (iN < iNLen)) {
				;
			} else {
				return new SimpleRtnBeen(E_XPBOXCHG_BOX_SLOT_CHK_FAILED,
						"产品ID[" + Prd.getPrd_seq_id() + "],箱号["
								+ box.getBox_id() + "] 子格位检查NG!");
			}
		}

		return new SimpleRtnBeen(prdList);
	}

	/**
	 * 更新Prd信息至目标箱子
	 * 
	 * @param old_prdList
	 * @param new_prdList
	 */
	private long realChgPrdInfo() {
		if (null != gOld_prdList) {
			for (Ret_prd_info prd : gOld_prdList) {
				prd.setEvt_cate(EVT_BOX_CHANGE);
				prd.setEvt_usr(inTrx.getEvt_user());
				prd.setEvt_timestamp(gEvtTimestamp);
				prd.setEvt_time_d(gEvtTimeD);
				prd.setSht_ope_msg(inTrx.getRemark());
				logger.info("Old [" + prd.getPrd_seq_id() + "]["
						+ prd.getWo_id_fk() + "]");
			}
		}

		if (null != gNew_prdList) {
			for (Ret_prd_info prd : gNew_prdList) {
				prd.setEvt_cate(EVT_BOX_CHANGE);
				prd.setEvt_usr(inTrx.getEvt_user());
				prd.setEvt_timestamp(gEvtTimestamp);
				prd.setEvt_time_d(gEvtTimeD);
				logger.info("New [" + prd.getPrd_seq_id() + "]["
						+ prd.getWo_id_fk() + "]");
				prd.setSht_ope_msg(inTrx.getRemark());
			}
		}

		return _NORMAL;
	}

	/**
	 * 配置Box信息
	 */
	private long configBoxProc() {
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);

		rtnBeen = retBoxDao.configBoxInfo(gOld_box);
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}
		rtnBeen = retBoxDao.configBoxInfo(gNew_box);
		if (_NORMAL != rtnBeen.getlRc()) {
			gszMsgBuf = rtnBeen.getMsgBuf();
			return rtnBeen.getlRc();
		}

		return _NORMAL;
	}
	
	private long checkPrdQrsProc(){
		
		String hql1 = "FROM Ret_prd_info where prd_seq_id in (";
		List<XpboxchgIA_N> iaryNList = inTrx.getIary_new();
		long lRc= _NORMAL;
		if(iaryNList!=null){
			for(XpboxchgIA_N iaryN : iaryNList){
				logger.info("new prd:"+iaryN.getPrd_seq_id());
				hql1 = hql1 + "'" + iaryN.getPrd_seq_id() + "'";
				if(iaryNList.indexOf(iaryN)!=iaryNList.size()-1){
					hql1 = hql1 + ",";
				}
			}
			hql1 = hql1 + ")";
			List<Ret_prd_info> newShtList = retPrdInfoDao.find(hql1);
			logger.info("new size:" + iaryNList.size());
			lRc = CheckQrsOverFlgMixProc(newShtList); 
			if(lRc !=_NORMAL){
				return lRc;
			}
		}
		
		
		String hql2 = "FROM Ret_prd_info where prd_seq_id in (";
		List<XpboxchgIA_O> iaryOList = inTrx.getIary_old();
		if(iaryOList!=null){
			logger.info("old size:" + iaryOList.size());
			for(XpboxchgIA_O iaryO : iaryOList){
				logger.info("old prd:"+iaryO.getPrd_seq_id());
				hql2 = hql2 + "'" + iaryO.getPrd_seq_id() + "'";
				if(iaryOList.indexOf(iaryO)!=iaryOList.size()-1){
					hql2 = hql2 + ",";
				}
			}
			hql2 = hql2 + ")";
			List<Ret_prd_info> oldShtList = retPrdInfoDao.find(hql2);
			lRc = CheckQrsOverFlgMixProc(oldShtList); 
			if(lRc !=_NORMAL){
				return lRc;
			}
		}
		
		return _NORMAL;
		
		
	}
	private long CheckQrsOverFlgMixProc(List<Ret_prd_info> retPrdInfoList){
		String qrsOvrFlg1 ,qrsOvrFlg2;
		
		qrsOvrFlg1 = retPrdInfoList.get(0).getQrs_ovr_flg();
		for (int i = 1; i < retPrdInfoList.size(); i++) {
			qrsOvrFlg2 = retPrdInfoList.get(i).getQrs_ovr_flg();
			if(qrsOvrFlg2==null){
				qrsOvrFlg2 = "";
			}
			if(!qrsOvrFlg2.equals(qrsOvrFlg1)){
				gszMsgBuf = "跨制程段产品不能混装,错误";
				return 1;
			}
		}
		return _NORMAL;
	}

}
